<template>
    <div>
        <div :id="`${id}-toolbar`">
            <button class="ql-bold" title="粗体"></button>
            <button class="ql-italic" title="斜体"></button>
            <button class="ql-underline" title="下划线"></button>
            <button class="ql-strike" title="删除线"></button>
            <select class="ql-size" title="字体大小">
                <option value="small"></option>
                <option selected></option>
                <option value="large"></option>
                <option value="huge"></option>
            </select>
            <select class="ql-header" title="标题大小">
                <option value="1"></option>
                <option value="2"></option>
                <option value="3"></option>
                <option value="4"></option>
                <option value="5"></option>
                <option value="6"></option>
                <option selected></option>
            </select>
            <select class="ql-font" title="字体"></select>
            <select class="ql-align" title="对齐方式"></select>
            <select class="ql-color" title="字体颜色"></select>
            <select class="ql-background" title="背景颜色"></select>
            <button class="ql-blockquote" title="引用"></button>
            <button class="ql-code-block" title="代码块"></button>
            <button class="ql-list" value="ordered" title="数字列表"></button>
            <button class="ql-list" value="bullet" title="点列表"></button>
            <button class="ql-script" value="sub" title="右下标"></button>
            <button class="ql-script" value="super" title="右上标"></button>
            <button class="ql-indent" value="-1" title="向左缩进"></button>
            <button class="ql-indent" value="+1" title="向右缩进"></button>
            <button class="ql-clean" title="清空样式"></button>

            <button class="ql-link" title="链接"></button>
            <button class="ql-image" title="插入图片" v-if="base64"></button>
            <div class="q-menu" title="插入图片" v-if="!base64">
                <Upload
                    :action="uploadFileUrl"
                    :headers="accessToken"
                    :on-success="handleSuccess"
                    :on-error="handleError"
                    :format="['jpg', 'jpeg', 'png', 'gif', 'bmp']"
                    accept=".jpg, .jpeg, .png, .gif, .bmp"
                    :max-size="5120"
                    :on-format-error="handleFormatError"
                    :on-exceeded-size="handleMaxSize"
                    :before-upload="beforeUpload"
                    :show-upload-list="false"
                    ref="qup"
                >
                    <Icon type="md-images" size="20" />
                </Upload>
            </div>
            <button class="ql-video" title="插入视频链接"></button>
            <div class="q-menu" title="编辑HTML代码" @click="editHTML" v-if="expandHtml">
                <Icon type="md-code-working" size="22" />
            </div>
            <div class="q-menu" title="预览" @click="fullscreenModal = true" v-if="expandPreview">
                <Icon type="ios-eye" size="24" />
            </div>
            <div class="q-menu" title="清空" @click="clear" v-if="expandClear">
                <Icon type="md-trash" size="18" style="display: block" />
            </div>
        </div>

        <div :id="id" :style="{ height: height }"></div>

        <Modal title="编辑html代码" v-model="showHTMLModal" :mask-closable="false" :width="900" :fullscreen="full">
            <Input v-if="!full" v-model="dataEdit" :rows="15" type="textarea" style="max-height: 60vh; overflow: auto" />
            <Input v-if="full" v-model="dataEdit" :rows="32" type="textarea" />
            <div slot="footer">
                <Button @click="full = !full" icon="md-expand">全屏开/关</Button>
                <Button @click="editHTMLOk" type="primary" icon="md-checkmark-circle-outline">确定保存</Button>
            </div>
        </Modal>
        <Modal title="预览" v-model="fullscreenModal" fullscreen>
            <div v-html="data">{{ data }}</div>
            <div slot="footer">
                <Button @click="fullscreenModal = false">关闭</Button>
            </div>
        </Modal>
    </div>
</template>

<script>
import { uploadFile } from '@/api/index';
import Quill from 'quill';
import 'quill/dist/quill.snow.css';
import xss from 'xss';
export default {
    name: 'editor',
    props: {
        id: {
            type: String,
            default: 'quill'
        },
        value: String,
        base64: {
            type: Boolean,
            default: false
        },
        height: {
            type: String,
            default: '300px'
        },
        expandHtml: {
            type: Boolean,
            default: true
        },
        expandPreview: {
            type: Boolean,
            default: true
        },
        expandClear: {
            type: Boolean,
            default: true
        },
        openXss: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            accessToken: {},
            uploadFileUrl: uploadFile,
            editor: null,
            options: {
                theme: 'snow',
                modules: {
                    toolbar: `#${this.id}-toolbar`
                },
                placeholder: '在这输入内容 ...'
            },
            data: this.value, // 富文本数据
            dataEdit: '', // 编辑数据
            showHTMLModal: false, // 显示html
            full: false, // html全屏开关
            fullscreenModal: false // 显示全屏预览
        };
    },
    methods: {
        initEditor() {
            this.accessToken = {
                accessToken: this.getStore('accessToken')
            };
            this.editor = new Quill(`#${this.id}`, this.options);
            let that = this;
            if (this.value) {
                this.editor.pasteHTML(this.value);
            }
            this.editor.on('text-change', function (delta, oldDelta, source) {
                let html = that.editor.container.firstChild.innerHTML;
                if (that.openXss) {
                    that.data = xss(html);
                } else {
                    that.data = html;
                }
                that.$emit('input', that.data);
                that.$emit('on-change', that.data);
            });
        },
        handleFormatError(file) {
            this.$Notice.warning({
                title: '不支持的文件格式',
                desc: '所选文件‘ ' + file.name + ' ’格式不正确, 请选择 .jpg .jpeg .png .gif .bmp格式文件'
            });
        },
        handleMaxSize(file) {
            this.$Notice.warning({
                title: '文件大小过大',
                desc: '所选文件‘ ' + file.name + ' ’大小过大, 不得超过 5M.'
            });
        },
        beforeUpload() {
            return true;
        },
        handleSuccess(res, file) {
            if (res.success) {
                let url = res.result;
                // 获取光标位置
                let range = this.editor.getSelection(true);
                // 总元素
                let delta = this.editor.getContents().length;
                let index;
                if (range) {
                    index = range.index;
                } else {
                    index = delta;
                }
                // 插入元素
                this.editor.insertEmbed(index, 'image', url);
                this.editor.setSelection(index + 1, 0);
            } else {
                // this.$Message.error(res.message);
                this.$Message.error({
                    content: res.message,
                    duration: 5,
                    closable: true
                });
            }
        },
        handleError(error, file, fileList) {
            // this.$Message.error(error.toString());
            this.$Message.error({
                content: error.toString(),
                duration: 5,
                closable: true
            });
        },
        editHTML() {
            this.dataEdit = this.data;
            this.showHTMLModal = true;
        },
        editHTMLOk() {
            this.editor.pasteHTML(this.dataEdit);
            this.$emit('input', this.data);
            this.$emit('on-change', this.data);
            this.showHTMLModal = false;
        },
        clear() {
            this.$Modal.confirm({
                title: '确认清空',
                content: '确认要清空编辑器内容？清空后不能撤回',
                onOk: () => {
                    this.data = '';
                    this.editor.pasteHTML(this.data);
                    this.$emit('input', this.data);
                    this.$emit('on-change', this.data);
                }
            });
        },
        setData(value) {
            if (!this.editor) {
                this.initEditor();
            }
            if (value != this.data) {
                this.data = value;
                let index = this.editor.selection.savedRange.index;
                this.editor.pasteHTML(this.data);
                this.editor.setSelection(index, 0);
                this.$emit('input', this.data);
                this.$emit('on-change', this.data);
            }
        }
    },
    watch: {
        value(val) {
            this.setData(val);
        }
    },
    mounted() {
        this.initEditor();
    }
};
</script>

<style lang="less">
.q-menu {
    margin: 0 3px;
    display: inline-block;
    cursor: pointer;
    color: #444;
    :hover {
        color: #06c;
    }
}
.ql-tooltip {
    left: 30% !important;
}

// 中文
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    border-right: 0px;
    content: '保存';
    padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode='video']::before {
    content: '请输入视频地址:';
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
    content: '14px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before {
    content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before {
    content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before {
    content: '32px';
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
    content: '标题';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
    content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
    content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
    content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
    content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
    content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
    content: '标题6';
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
    content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
    content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
    content: '等宽字体';
}
</style>
